﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml.Serialization;
using Obra.Api;
using Obra.Common;
using System.Globalization;

namespace Obra.SmugMug.Api
{
    public class ImageContract : 
        ResponseWithIdContract,
        IMedia
    {
        /// <summary>
        /// System.URI is not serializable with the XML serializer because 
        /// System.URI does not provide a parameterless constructor, therefore;
        /// all of the URLs shown below are deserialized to a string.
        /// </summary>
        #region URLs

        [XmlAttribute("AlbumURL")]
        public string AlbumUrl
        {
            get;
            set;
        }
        
        [XmlAttribute("ThumbURL")]
        public string ThumbUrl
        {
            get;
            set;
        }

        [XmlAttribute("TinyURL")]
        public string TinyUrl
        {
            get;
            set;
        }

        [XmlAttribute("SmallURL")]
        public string SmallUrl
        {
            get;
            set;
        }

        [XmlAttribute("MediumURL")]
        public string MediumUrl
        {
            get;
            set;
        }

        [XmlAttribute("LargeURL")]
        public string LargeUrl
        {
            get;
            set;
        }

        [XmlAttribute("OriginalURL")]
        public string OriginalUrl
        {
            get;
            set;
        }

        [XmlAttribute("XLargeURL")]
        public string XLargeUrl
        {
            get;
            set;
        }

        [XmlAttribute("X2LargeURL")]
        public string X2LargeUrl
        {
            get;
            set;
        }

        [XmlAttribute("X3LargeURL")]
        public string X3LargeUrl
        {
            get;
            set;
        }

        [XmlAttribute("Video320URL")]
        public string Video320Url
        {
            get;
            set;
        }
        
        [XmlAttribute("Video640URL")]
        public string Video640Url
        {
            get;
            set;
        }
        
        [XmlAttribute("Video960URL")]
        public string Video960Url
        {
            get;
            set;
        }
        
        [XmlAttribute("Video1280URL")]
        public string Video1280Url
        {
            get;
            set;
        }

        #endregion URLs

        #region Dates

        [XmlAttribute("Date")]
        public string DateString
        {
            get;
            set;
        }

        public DateTime Date
        {
            get { return SmugMugDateTime.Parse(this.DateString); }
        }

        /// <summary>
        /// SmugMug does not provide the date in XSD format, which makes the 
        /// code a little bit more complicated.  If they did, this would just
        /// work.
        /// </summary>
        [XmlAttribute("LastUpdated")]
        public string LastUpdatedString
        {
            get;
            set;
        }

        /// <summary>
        /// Convert SmugMug's format into .NEt DateTime.
        /// </summary>
        public DateTime LastModified
        {
            get { return SmugMugDateTime.Parse(this.LastUpdatedString); }
        }        

        #endregion Dates

        #region Location

        /// <summary>
        /// TODO: Does .NET have a longtitude type?
        /// </summary>
        [XmlAttribute("Latitude")]
        public string Latitude
        {
            get;
            set;
        }

        [XmlAttribute("Longitude")]
        public string Longitude
        {
            get; 
            set;
        }

        
        [XmlAttribute("Altitude")]
        public string Altitude
        {
            get; 
            set;
        }
        
        #endregion Location

        #region File Specific

        [XmlAttribute("Size")]
        public int Size
        {
            get;
            set;
        }

        [XmlAttribute("FileName")]
        public string FileName
        {
            get;
            set;
        }

        /// <summary>
        /// TODO: should this be an ENUM?  Yes, but what are the formats?
        /// </summary>
        [XmlAttribute("Format")]
        public string Format
        {
            get;
            set;
        }

        [XmlAttribute("Width")]
        public int Width
        {
            get;
            set;
        }

        [XmlAttribute("Height")]
        public int Height
        {
            get;
            set;
        }

        #endregion File Specific

        [XmlAttribute("Hidden")]
        public bool Hidden
        {
            get;
            set;
        }

        [XmlAttribute("Serial")]
        public int Serial
        {
            get;
            set;
        }

        [XmlAttribute("Watermark")]
        public string Watermark
        {
            get;
            set;
        }

        [XmlAttribute("Key")]
        public string Key
        {
            get;
            set;
        }

        [XmlAttribute("Keywords")]
        public string Keywords
        {
            get;
            set;
        }

        [XmlAttribute("MD5Sum")]
        public string MD5Sum
        {
            get;
            set;
        }

        [XmlAttribute("Position")]
        public int Position
        {
            get;
            set;
        }

        [XmlAttribute("Caption")]
        public string Caption
        {
            get;
            set;
        }

        /// <summary>
        /// A simplified album contract that only contains minimal album 
        /// information: Key, id.
        /// </summary>
        public class ShortAlbumContract
            : ResponseWithIdContract
        {
            [XmlAttribute("Key")]
            public string Key
            {
                get;
                set;
            }
        }

        /// <summary>
        /// The album of this image.
        /// </summary>
        /// <remarks>
        /// <para>
        /// I think this is a HACK, but I am not positive.  I want to use 
        /// AlbumContract, but I no longer can because of the following error
        /// message.
        /// </para>
        /// <para>
        /// Obra.Test.DeserializeTester.SmugMugImages:
        ///   System.InvalidOperationException : There was an error reflecting type 'Obra.SmugMug.Api.ImagesContract'.
        ///   ----> System.InvalidOperationException : There was an error reflecting property 'Image'.
        ///   ----> System.InvalidOperationException : There was an error reflecting type 'Obra.SmugMug.Api.ImageContract'.
        ///   ----> System.InvalidOperationException : Cannot serialize member 'Obra.SmugMug.Api.ImageContract.Album' of type 'Obra.SmugMug.Api.AlbumContract', see inner exception for more details.
        ///   ----> System.NotSupportedException : Cannot serialize member Obra.SmugMug.Api.ImageContract.Album of type Obra.Api.IMedia because it is an interface.
        /// </para>
        /// </remarks>
        [XmlElement("Album")]
        public ShortAlbumContract Album
        {
            get;
            set;
        }

        public int AlbumId
        {
            get { return this.Album.Id; }
        }

        public string AlbumKey
        {
            get { return this.Album.Key; }
        }

        #region IMedia Members

        /// <summary>
        /// Size of this media in bytes.
        /// </summary>
        [XmlIgnore]
        public ulong SizeInBytes
        {
            get { return (ulong)this.Size; }
        }

        /// <summary>
        /// Checksum of this media file.
        /// </summary>
        public string Checksum
        {
            get { return this.MD5Sum; }
            //get { return this.Checksum; }
        }

        /// <summary>
        /// URL where this media can be fetched from.
        /// </summary>
        [XmlIgnore]
        public Uri Url
        {
            get { return new Uri(this.OriginalUrl); }
        }

        #endregion

        #region IEntity Members

        /// <summary>
        /// Name of this media.
        /// </summary>
        [XmlIgnore]
        public string Name
        {
            get { return this.FileName; }
        }

        /// <summary>
        /// Description of this media.
        /// </summary>
        [XmlIgnore]
        public string Description
        {
            get { return this.Caption; }
        }

         /// <summary>
         /// Unique identifier for this image.
         /// </summary>
        [XmlIgnore]
        string IEntity.Id
        {
            get { return this.Id.ToString(); }
        }

        /// <summary>
        /// List of tags (keywords) for this media.
        /// XXX: revisit this - I need to move Obra.SmugMug.Api.Keywords to common or API.
        /// </summary>
        [XmlIgnore]
        public IList<string> Tags
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }
}
